package cn.funeralobjects.minecraft.service.impl;

import cn.funeralobjects.minecraft.config.McAppConfiguration;
import cn.funeralobjects.minecraft.model.Player;
import cn.funeralobjects.minecraft.model.Server;
import cn.funeralobjects.minecraft.service.MinecraftServerService;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.UUID;

/**
 * @author FuneralObjects
 * Create date: 2020/11/11 7:11 AM
 */
@Service
public class MinecraftServerServiceImpl implements MinecraftServerService {

    private PlayerManager playerManager;

    @PostConstruct
    private void init() {
        playerManager = McAppConfiguration.minecraftServer.getPlayerManager();
    }


    @Override
    public Mono<Server> getServer() {
        return Mono.justOrEmpty(playerManager.getServer())
                .map(MinecraftServerServiceImpl::toModel);
    }

    @Override
    public Mono<Player> getPlayer(String uuid) {
        return Mono.justOrEmpty(playerManager.getPlayer(uuid))
                .map(MinecraftServerServiceImpl::toModel);
    }

    @Override
    public Flux<Player> getPlayers() {
        return Flux.fromIterable(playerManager.getPlayerList())
                .map(MinecraftServerServiceImpl::toModel);
    }

    @Override
    public Mono<Integer> currentPlayerCount() {
        return Mono.justOrEmpty(playerManager.getCurrentPlayerCount());
    }

    @Override
    public Mono<Player> kick(String uuid) {
        return Mono.justOrEmpty(uuid)
                .map(UUID::fromString)
                .flatMap(uuidObj -> {
                    ServerPlayerEntity pe = playerManager.getPlayer(uuidObj);
                    return pe == null ? Mono.empty() : Mono.just(pe);
                })
                .map(pe -> {
                    pe.networkHandler.disconnect(new LiteralText("You were kicked by the server."));
                    return toModel(pe);
                });
    }

    private static Player toModel(PlayerEntity pe) {
        return pe == null ? null : new Player().setName(pe.getEntityName())
                .setUuid(pe.getUuid().toString());
    }

    private static Server toModel(MinecraftServer minecraftServer) {
        return minecraftServer == null ? null : new Server()
                .setIp(minecraftServer.getServerIp())
                .setOnlinePlayerCount(minecraftServer.getCurrentPlayerCount())
                .setVersion(minecraftServer.getVersion())
                .setDefaultGameMode(minecraftServer.getDefaultGameMode().getName())
                .setPort(minecraftServer.getServerPort());
    }
}
